package com.example.mylibrarybase.yumengmeng25.utils;

/**
 * Base64 tool 2011
 * 
 * @author Administrator
 * 
 */
public class Base64 {
	/** Specify encoding (value is <tt>true</tt>). */
	public final static boolean ENCODE = true;

	/** Specify decoding (value is <tt>false</tt>). */
	public final static boolean DECODE = false;

	/** Maximum line length (76) of Base64 output. */
	private final static int MAX_LINE_LENGTH = 76;

	/** The equals sign (=) as a byte. */
	private final static byte EQUALS_SIGN = (byte) '=';

	/** The new line character (\n) as a byte. */
	private final static byte NEW_LINE = (byte) '\n';

	/** The 64 valid Base64 values. */
	private final static byte[] ALPHABET = { (byte) 'A', (byte) 'B',
			(byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',
			(byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
			(byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q',
			(byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
			(byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
			(byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
			(byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k',
			(byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
			(byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',
			(byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',
			(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',
			(byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',
			(byte) '+', (byte) '/' };

	/**
	 * Translates a Base64 value to either its 6-bit reconstruction value or a
	 * negative number indicating some other meaning.
	 **/
	private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9,
			-9, // Decimal 0 - 8
			-5, -5, -9, -9, -5, -9, -9, -9, -9, // Whitespace: Tab and Linefeed,
			// Decimal 11 - 12, Whitespace:
			// Carriage Return
			-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
			-9, -9, -9, -9, -9, -5, -9, -9, -9, // Decimal 27 - 31, Whitespace:
			// Space
			-9, -9, -9, -9, -9, -9, -9, 62, -9, // Decimal 33 - 42, Plus sign at
			// decimal 43
			-9, -9, 63, 52, 53, 54, 55, 56, 57, // Decimal 44 - 46, Slash at
			// decimal 47
			58, 59, 60, 61, -9, -9, -9, -1, -9, // Numbers zero through nine,
			// Decimal 58 - 60, Equals sign
			// at decimal 61
			-9, -9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // Decimal 62 - 64
			10, 11, 12, 13, 14, 15, 16, 17, 18, // Letters 'A' through 'N'
			19, 20, 21, 22, 23, 24, 25, -9, -9, // Letters 'O' through 'Z'
			-9, -9, -9, -9, 26, 27, 28, 29, 30, // Decimal 91 - 96
			31, 32, 33, 34, 35, 36, 37, 38, 39, // Letters 'a' through 'm'
			40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -9, -9, -9, -9 // Letters
	// 'n'
	// through
	// 'z',
	// Decimal
	// 123
	// -
	// 126
	/*
	 * ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
	 * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255
	 */
	};

	private final static byte BAD_ENCODING = -9; // Indicates error in encoding
	private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in
	// encoding
	private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in

	// encoding

	/** Defeats instantiation. */
	private Base64() {
	}

	/** Testing. */
	public static void main(String[] args) {
		String s = "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";
		// s = System.getProperties().toString();
		// System.out.println( s + ": \n [" + encode( s ) + "]\n [" +
		// decode(encode(s)) + "]" );

		byte[] b = decode(s);
		try {
			String ss = CryptoTools.decrypt(b);
			System.out.println(ss);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/* ******** E N C O D I N G M E T H O D S ******** */

	/**
	 * Encodes the first three bytes of array <var>threeBytes</var> and returns
	 * a four-byte array in Base64 notation.
	 * 
	 * @param threeBytes
	 *            the array to convert
	 * @return four byte array in Base64 notation.
	 * @since 1.3
	 */
	private static byte[] encode3to4(byte[] threeBytes) {
		return encode3to4(threeBytes, 3);
	} // end encodeToBytes

	/**
	 * Encodes up to the first three bytes of array <var>threeBytes</var> and
	 * returns a four-byte array in Base64 notation. The actual number of
	 * significant bytes in your array is given by <var>numSigBytes</var>. The
	 * array <var>threeBytes</var> needs only be as big as
	 * <var>numSigBytes</var>.
	 * 
	 * @param threeBytes
	 *            the array to convert
	 * @param numSigBytes
	 *            the number of significant bytes in your array
	 * @return four byte array in Base64 notation.
	 * @since 1.3
	 */
	private static byte[] encode3to4(byte[] threeBytes, int numSigBytes) {
		byte[] dest = new byte[4];
		encode3to4(threeBytes, 0, numSigBytes, dest, 0);
		return dest;
	}

	/**
	 * Encodes up to three bytes of the array <var>source</var> and writes the
	 * resulting four Base64 bytes to <var>destination</var>. The source and
	 * destination arrays can be manipulated anywhere along their length by
	 * specifying <var>srcOffset</var> and <var>destOffset</var>. This method
	 * does not check to make sure your arrays are large enough to accomodate
	 * <var>srcOffset</var> + 3 for the <var>source</var> array or
	 * <var>destOffset</var> + 4 for the <var>destination</var> array. The
	 * actual number of significant bytes in your array is given by
	 * <var>numSigBytes</var>.
	 * 
	 * @param source
	 *            the array to convert
	 * @param srcOffset
	 *            the index where conversion begins
	 * @param numSigBytes
	 *            the number of significant bytes in your array
	 * @param destination
	 *            the array to hold the conversion
	 * @param destOffset
	 *            the index where output will be put
	 * @return the <var>destination</var> array
	 * @since 1.3
	 */
	private static byte[] encode3to4(byte[] source, int srcOffset,
			int numSigBytes, byte[] destination, int destOffset) {
		// 1 2 3
		// 01234567890123456789012345678901 Bit position
		// --------000000001111111122222222 Array position from threeBytes
		// --------| || || || | Six bit groups to index ALPHABET
		// >>18 >>12 >> 6 >> 0 Right shift necessary
		// 0x3f 0x3f 0x3f Additional AND

		// Create buffer with zero-padding if there are only one or two
		// significant bytes passed in the array.
		// We have to shift left 24 in order to flush out the 1's that appear
		// when Java treats a value as negative that is cast from a byte to an
		// int.
		int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
				| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
				| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);

		switch (numSigBytes) {
		case 3:
			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
			destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
			destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
			return destination;

		case 2:
			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
			destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
			destination[destOffset + 3] = EQUALS_SIGN;
			return destination;

		case 1:
			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
			destination[destOffset + 2] = EQUALS_SIGN;
			destination[destOffset + 3] = EQUALS_SIGN;
			return destination;

		default:
			return destination;
		} // end switch
	} // end encode3to4

	/**
	 * Serializes an object and returns the Base64-encoded version of that
	 * serialized object. If the object cannot be serialized or there is another
	 * error, the method will return <tt>null</tt>.
	 * 
	 * @param serializableObject
	 *            The object to encode
	 * @return The Base64-encoded object
	 * @since 1.4
	 */
	public static String encodeObject(java.io.Serializable serializableObject) {
		java.io.ByteArrayOutputStream baos = null;
		java.io.OutputStream b64os = null;
		java.io.ObjectOutputStream oos = null;

		try {
			baos = new java.io.ByteArrayOutputStream();
			b64os = new OutputStream(baos, Base64.ENCODE);
			oos = new java.io.ObjectOutputStream(b64os);

			oos.writeObject(serializableObject);
		} catch (java.io.IOException e) { // end try
			e.printStackTrace();
			return null;
		} finally { // end catch
			try {
				oos.close();
			} catch (Exception e) {
			}
			try {
				b64os.close();
			} catch (Exception e) {
			}
			try {
				baos.close();
			} catch (Exception e) {
			}
		} // end finally

		return new String(baos.toByteArray());
	} // end encode

	/**
	 * Encodes a byte array into Base64 notation. Equivalen to calling
	 * <code>encodeBytes( source, 0, source.length )</code>
	 * 
	 * @param source
	 *            The data to convert
	 * @since 1.4
	 */
	public static String encodeBytes(byte[] source) {
		return encodeBytes(source, 0, source.length);
	} // end encodeBytes

	/**
	 * Encodes a byte array into Base64 notation.
	 * 
	 * @param source
	 *            The data to convert
	 * @param off
	 *            Offset in array where conversion should begin
	 * @param len
	 *            Length of data to convert
	 * @since 1.4
	 */
	public static String encodeBytes(byte[] source, int off, int len) {
		int len43 = len * 4 / 3;
		byte[] outBuff = new byte[(len43) + ((len % 3) > 0 ? 4 : 0) + // Main
				// 4:3,
				// Account
				// for
				// padding
				(len43 / MAX_LINE_LENGTH)]; // New lines
		int d = 0;
		int e = 0;
		int len2 = len - 2;
		int lineLength = 0;
		for (; d < len2; d += 3, e += 4) {
			encode3to4(source, d, 3, outBuff, e);

			lineLength += 4;
			if (lineLength == MAX_LINE_LENGTH) {
				outBuff[e + 4] = NEW_LINE;
				e++;
				lineLength = 0;
			} // end if: end of line
		} // en dfor: each piece of array

		if (d < len) {
			encode3to4(source, d, len - d, outBuff, e);
			e += 4;
		} // end if: some padding needed

		return new String(outBuff, 0, e);
	} // end encodeBytes

	/**
	 * Encodes a string in Base64 notation with line breaks after every 75
	 * Base64 characters.
	 * 
	 * @param s
	 *            the string to encode
	 * @return the encoded string
	 * @since 1.3
	 */
	public static String encodeString(String s) {
		return encodeBytes(s.getBytes());
	} // end encodeString

	/* ******** D E C O D I N G M E T H O D S ******** */

	/**
	 * Decodes the first four bytes of array <var>fourBytes</var> and returns an
	 * array up to three bytes long with the decoded values.
	 * 
	 * @param fourBytes
	 *            the array with Base64 content
	 * @return array with decoded values
	 * @since 1.3
	 */
	private static byte[] decode4to3(byte[] fourBytes) {
		byte[] outBuff1 = new byte[3];
		int count = decode4to3(fourBytes, 0, outBuff1, 0);
		byte[] outBuff2 = new byte[count];

		for (int i = 0; i < count; i++) {
			outBuff2[i] = outBuff1[i];
		}

		return outBuff2;
	}

	/**
	 * Decodes four bytes from array <var>source</var> and writes the resulting
	 * bytes (up to three of them) to <var>destination</var>. The source and
	 * destination arrays can be manipulated anywhere along their length by
	 * specifying <var>srcOffset</var> and <var>destOffset</var>. This method
	 * does not check to make sure your arrays are large enough to accomodate
	 * <var>srcOffset</var> + 4 for the <var>source</var> array or
	 * <var>destOffset</var> + 3 for the <var>destination</var> array. This
	 * method returns the actual number of bytes that were converted from the
	 * Base64 encoding.
	 * 
	 * 
	 * @param source
	 *            the array to convert
	 * @param srcOffset
	 *            the index where conversion begins
	 * @param destination
	 *            the array to hold the conversion
	 * @param destOffset
	 *            the index where output will be put
	 * @return the number of decoded bytes converted
	 * @since 1.3
	 */
	private static int decode4to3(byte[] source, int srcOffset,
			byte[] destination, int destOffset) {
		// Example: Dk==
		if (source[srcOffset + 2] == EQUALS_SIGN) {
			int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
					| ((DECODABET[source[srcOffset + 1]] << 24) >>> 12);

			destination[destOffset] = (byte) (outBuff >>> 16);
			return 1;
		}

		// Example: DkL=
		else if (source[srcOffset + 3] == EQUALS_SIGN) {
			int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
					| ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
					| ((DECODABET[source[srcOffset + 2]] << 24) >>> 18);

			destination[destOffset] = (byte) (outBuff >>> 16);
			destination[destOffset + 1] = (byte) (outBuff >>> 8);
			return 2;
		}

		// Example: DkLE
		else {
			int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
					| ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
					| ((DECODABET[source[srcOffset + 2]] << 24) >>> 18)
					| ((DECODABET[source[srcOffset + 3]] << 24) >>> 24);

			destination[destOffset] = (byte) (outBuff >> 16);
			destination[destOffset + 1] = (byte) (outBuff >> 8);
			destination[destOffset + 2] = (byte) (outBuff);
			return 3;
		}
	} // end decodeToBytes

	/**
	 * Decodes data from Base64 notation.
	 * 
	 * @param s
	 *            the string to decode
	 * @return the decoded data
	 * @since 1.4
	 */
	public static byte[] decode(String s) {
		byte[] bytes = s.getBytes();
		return decode(bytes, 0, bytes.length);
	} // end decode

	/**
	 * Decodes data from Base64 notation and returns it as a string. Equivlaent
	 * to calling <code>new String( decode( s ) )</code>
	 * 
	 * @param s
	 *            the strind to decode
	 * @return The data as a string
	 * @since 1.4
	 */
	public static String decodeToString(String s) {
		return new String(decode(s));
	} // end decodeToString

	/**
	 * Attempts to decode Base64 data and deserialize a Java Object within.
	 * Returns <tt>null if there was an error.
	 * 
	 * @param encodedObject
	 *            The Base64 data to decode
	 * @return The decoded and deserialized object
	 * @since 1.4
	 */
	public static Object decodeToObject(String encodedObject) {
		byte[] objBytes = decode(encodedObject);

		java.io.ByteArrayInputStream bais = null;
		java.io.ObjectInputStream ois = null;

		try {
			bais = new java.io.ByteArrayInputStream(objBytes);
			ois = new java.io.ObjectInputStream(bais);

			return ois.readObject();
		} catch (java.io.IOException e) { // end try
			e.printStackTrace();
			return null;
		} catch (ClassNotFoundException e) { // end catch
			e.printStackTrace();
			return null;
		} finally { // end catch
			try {
				bais.close();
			} catch (Exception e) {
			}
			try {
				ois.close();
			} catch (Exception e) {
			}
		} // end finally
	} // end decodeObject

	/**
	 * Decodes Base64 content in byte array format and returns the decoded byte
	 * array.
	 * 
	 * @param source
	 *            The Base64 encoded data
	 * @param off
	 *            The offset of where to begin decoding
	 * @param len
	 *            The length of characters to decode
	 * @return decoded data
	 * @since 1.3
	 */
	public static byte[] decode(byte[] source, int off, int len) {
		int len34 = len * 3 / 4;
		byte[] outBuff = new byte[len34]; // Upper limit on size of output
		int outBuffPosn = 0;

		byte[] b4 = new byte[4];
		int b4Posn = 0;
		int i = 0;
		byte sbiCrop = 0;
		byte sbiDecode = 0;
		for (i = 0; i < len; i++) {
			sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits
			sbiDecode = DECODABET[sbiCrop];

			if (sbiDecode >= WHITE_SPACE_ENC) { // White space, Equals sign or
				// better
				if (sbiDecode >= EQUALS_SIGN_ENC) {
					b4[b4Posn++] = sbiCrop;
					if (b4Posn > 3) {
						outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
						b4Posn = 0;

						// If that was the equals sign, break out of 'for' loop
						if (sbiCrop == EQUALS_SIGN) {
							break;
						}
					} // end if: quartet built

				} // end if: equals sign or better

			} else { // end if: white space, equals sign or better
				System.err.println("Bad Base64 input character at " + i + ": "
						+ source[i] + "(decimal)");
				return null;
			} // end else:
		} // each input character

		byte[] out = new byte[outBuffPosn];
		System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
		return out;
	} // end decode

	/* ******** I N N E R C L A S S I N P U T S T R E A M ******** */

	/**
	 * A {@link InputStream} will read data from another
	 * {@link java.io.InputStream}, given in the constructor, and encode/decode
	 * to/from Base64 notation on the fly.
	 * 
	 * @see Base64
	 * @see java.io.FilterInputStream
	 * @since 1.3
	 */
	public static class InputStream extends java.io.FilterInputStream {
		private boolean encode; // Encoding or decoding
		private int position; // Current position in the buffer
		private byte[] buffer; // Small buffer holding converted data
		private int bufferLength; // Length of buffer (3 or 4)
		private int numSigBytes; // Number of meaningful bytes in the buffer

		/**
		 * Constructs a {@link InputStream} in DECODE mode.
		 * 
		 * @param in
		 *            the {@link java.io.InputStream} from which to read data.
		 * @since 1.3
		 */
		public InputStream(java.io.InputStream in) {
			this(in, Base64.DECODE);
		} // end constructor

		/**
		 * Constructs a {@link InputStream} in either ENCODE or DECODE
		 * mode.
		 * 
		 * @param in
		 *            the {@link java.io.InputStream} from which to read data.
		 * @param encode
		 *            Conversion direction
		 * @see Base64#ENCODE
		 * @see Base64#DECODE
		 * @since 1.3
		 */
		public InputStream(java.io.InputStream in, boolean encode) {
			super(in);
			this.encode = encode;
			this.bufferLength = encode ? 4 : 3;
			this.buffer = new byte[bufferLength];
			this.position = -1;
		} // end constructor

		/**
		 * Reads enough of the input stream to convert to/from Base64 and
		 * returns the next byte.
		 * 
		 * @return next byte
		 * @since 1.3
		 */
		public int read() throws java.io.IOException {
			// Do we need to get data?
			if (position < 0) {
				if (encode) {
					byte[] b3 = new byte[3];
					numSigBytes = 0;
					for (int i = 0; i < 3; i++) {
						try {
							int b = in.read();

							// If end of stream, b is -1.
							if (b >= 0) {
								b3[i] = (byte) b;
								numSigBytes++;
							} // end if: not end of stream

						} catch (java.io.IOException e) { // end try: read
							// Only a problem if we got no data at all.
							if (i == 0) {
								throw e;
							}

						} // end catch
					} // end for: each needed input byte

					if (numSigBytes > 0) {
						encode3to4(b3, 0, numSigBytes, buffer, 0);
						position = 0;
					} // end if: got data
				} // end if: encoding

				// Else decoding
				else {
					byte[] b4 = new byte[4];
					int i = 0;
					for (i = 0; i < 4; i++) {
						int b = 0;
						do {
							b = in.read();
						} while (b >= 0
								&& DECODABET[b & 0x7f] < WHITE_SPACE_ENC);

						if (b < 0) {
							break; // Reads a -1 if end of stream
						}

						b4[i] = (byte) b;
					} // end for: each needed input byte

					if (i == 4) {
						numSigBytes = decode4to3(b4, 0, buffer, 0);
						position = 0;
					} // end if: got four characters

				} // end else: decode
			} // end else: get data

			// Got data?
			if (position >= 0) {
				// End of relevant data?
				if (position >= numSigBytes) {
					return -1;
				}

				int b = buffer[position++];

				if (position >= bufferLength) {
					position = -1;
				}

				return b;
			} // end if: position >= 0

			// Else error
			else {
				return -1;
			}
		} // end read

		/**
		 * Calls {@link #read} repeatedly until the end of stream is reached or
		 * <var>len</var> bytes are read. Returns number of bytes read into
		 * array or -1 if end of stream is encountered.
		 * 
		 * @param dest
		 *            array to hold values
		 * @param off
		 *            offset for array
		 * @param len
		 *            max number of bytes to read into array
		 * @return bytes read into array or -1 if end of stream is encountered.
		 * @since 1.3
		 */
		public int read(byte[] dest, int off, int len)
				throws java.io.IOException {
			int i;
			int b;
			for (i = 0; i < len; i++) {
				b = read();

				if (b < 0) {
					return -1;
				}

				dest[off + i] = (byte) b;
			} // end for: each byte read
			return i;
		} // end read

	} // end inner class InputStream

	/* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */

	/**
	 * A {@link OutputStream} will write data to another
	 * {@link java.io.OutputStream}, given in the constructor, and encode/decode
	 * to/from Base64 notation on the fly.
	 * 
	 * @see Base64
	 * @see java.io.FilterOutputStream
	 * @since 1.3
	 */
	public static class OutputStream extends java.io.FilterOutputStream {
		private boolean encode;
		private int position;
		private byte[] buffer;
		private int bufferLength;
		private int lineLength;

		/**
		 * Constructs a {@link OutputStream} in ENCODE mode.
		 * 
		 * @param out
		 *            the {@link java.io.OutputStream} to which data will be
		 *            written.
		 * @since 1.3
		 */
		public OutputStream(java.io.OutputStream out) {
			this(out, Base64.ENCODE);
		} // end constructor

		/**
		 * Constructs a {@link OutputStream} in either ENCODE or DECODE
		 * mode.
		 * 
		 * @param out
		 *            the {@link java.io.OutputStream} to which data will be
		 *            written.
		 * @param encode
		 *            Conversion direction
		 * @see Base64#ENCODE
		 * @see Base64#DECODE
		 * @since 1.3
		 */
		public OutputStream(java.io.OutputStream out, boolean encode) {
			super(out);
			this.encode = encode;
			this.bufferLength = encode ? 3 : 4;
			this.buffer = new byte[bufferLength];
			this.position = 0;
			this.lineLength = 0;
		} // end constructor

		/**
		 * Writes the byte to the output stream after converting to/from Base64
		 * notation. When encoding, bytes are buffered three at a time before
		 * the output stream actually gets a write() call. When decoding, bytes
		 * are buffered four at a time.
		 * 
		 * @param theByte
		 *            the byte to write
		 * @since 1.3
		 */
		public void write(int theByte) throws java.io.IOException {
			buffer[position++] = (byte) theByte;
			if (position >= bufferLength) {
				if (encode) {
					out.write(Base64.encode3to4(buffer, bufferLength));

					lineLength += 4;
					if (lineLength >= MAX_LINE_LENGTH) {
						out.write(NEW_LINE);
						lineLength = 0;
					} // end if: end o fline
				} else { // end if: encoding
					out.write(Base64.decode4to3(buffer));
				}

				position = 0;
			} // end if: convert and flush
		} // end write

		/**
		 * Calls {@link #write} repeatedly until <var>len</var> bytes are
		 * written.
		 * 
		 * @param theBytes
		 *            array from which to read bytes
		 * @param off
		 *            offset for array
		 * @param len
		 *            max number of bytes to read into array
		 * @since 1.3
		 */
		public void write(byte[] theBytes, int off, int len)
				throws java.io.IOException {
			for (int i = 0; i < len; i++) {
				write(theBytes[off + i]);
			} // end for: each byte written

		} // end write

		/**
		 * Appropriately pads Base64 notation when encoding or throws an
		 * exception if Base64 input is not properly padded when decoding.
		 * 
		 * @since 1.3
		 */
		public void flush() throws java.io.IOException {
			if (position > 0) {
				if (encode) {
					out.write(Base64.encode3to4(buffer, position));
				} else { // end if: encoding
					throw new java.io.IOException(
							"Base64 input not properly padded.");
				} // end else: decoding
			} // end if: buffer partially full

			super.flush();
			out.flush();
		} // end flush

		/**
		 * Flushes and closes stream.
		 * 
		 * @since 1.3
		 */
		public void close() throws java.io.IOException {
			this.flush();

			super.close();
			out.close();

			buffer = null;
			out = null;
		} // end close
	} // end inner class OutputStream
} // end class Base64
